using System;
using System.Collections.Generic;
using Castle.ActiveRecord;
using CosyTrade.Core;
using CosyTrade.DataStorage;
using CosyTrade.Financial;
using NHibernate.Expression;

namespace CosyTrade.StoreManagement.Implement
{
    [Addin("ProductManager")]
    public class ProductManager : AddinBase, IProductManager
    {
        private IDataStorage dataStorage;

        protected override void OnInitialize()
        {
            base.OnInitialize();
            new ExchangeRate();
            dataStorage = (IDataStorage) CurrentAddinManager.GetAddin("DataStorage");
        }

        public int CalcProductListCount(ICriterion criterion)
        {
            ICriterion executeCriterion = Expression.Eq("IsDeleteObject", false);
            if (criterion != null) executeCriterion = Expression.And(executeCriterion, criterion);
            return ActiveRecordMediator<Product>.Count(executeCriterion);
        }

        public IList<Product> GetProductList(ICriterion criterion, int pageIndex, int pageSize, params Order[] orderBy)
        {
            int startRecord = (pageIndex - 1)*pageSize;
            ICriterion executeCriterion = Expression.Eq("IsDeleteObject", false);
            if (criterion != null) executeCriterion = Expression.And(executeCriterion, criterion);
            return ActiveRecordMediator<Product>.SlicedFindAll(startRecord, pageIndex*pageSize, orderBy, executeCriterion);
        }

        public void CreateProductCategory(ProductCategoryBase categoryInfo, Guid parentKey)
        {
            categoryInfo.IsNewObject = true;
            ActiveRecordMediator<ProductCategoryBase>.Create(categoryInfo);

            if (parentKey == Guid.Empty || categoryInfo.Parent == Guid.Empty) return;
            ProductCategory productCategory = ActiveRecordMediator<ProductCategory>.FindByPrimaryKey(parentKey);
            if (productCategory == null) return;
            productCategory.IsModifyObject = !productCategory.IsNewObject;
            productCategory.Childs.Add(categoryInfo);
            ActiveRecordMediator<ProductCategory>.Update(productCategory);
        }

        public void UpdateProductCategory(ProductCategoryBase categoryInfo,Guid oldKey)
        {
            categoryInfo.IsModifyObject = !categoryInfo.IsNewObject;
            ActiveRecordMediator<ProductCategoryBase>.Update(categoryInfo);

            if (oldKey == categoryInfo.Parent) return;
            if(oldKey!=Guid.Empty)
            {
                ProductCategory categoryBase = ActiveRecordMediator<ProductCategory>.FindOne(Expression.Eq("PrimaryKey", oldKey));
                if (categoryBase != null)
                {
                    foreach (ProductCategoryBase child in categoryBase.Childs)
                    {
                        if (child.PrimaryKey != categoryInfo.PrimaryKey) continue;
                        categoryBase.Childs.Remove(child);
                        break;
                    }

                    ActiveRecordMediator<ProductCategory>.Update(categoryBase);
                }
            }

            if (categoryInfo.Parent == Guid.Empty) return;
            ProductCategory productCategory = ActiveRecordMediator<ProductCategory>.FindByPrimaryKey(categoryInfo.Parent);
            if (productCategory == null) return;
            productCategory.Childs.Add(categoryInfo);
            ActiveRecordMediator<ProductCategory>.Update(productCategory);
        }

        public void DeleteProductCategory(Guid categoryGuid)
        {
            ProductCategoryBase categoryBase = ActiveRecordMediator<ProductCategoryBase>.FindByPrimaryKey(categoryGuid);

            if (categoryBase == null) return;

            IList<Product> products = GetProductList(Expression.Eq("Category", categoryBase), 1, int.MaxValue);
            ProductCategory productCategory = GetProductCategoryDetail(categoryBase.PrimaryKey);
            if ((products != null && products.Count > 0) || productCategory != null && productCategory.Childs != null && productCategory.Childs.Count > 0)
                return;
            if(categoryBase.IsNewObject) ActiveRecordMediator<ProductCategoryBase>.Delete(categoryBase);
            else
            {
                categoryBase.IsDeleteObject = true;
                ActiveRecordMediator<ProductCategoryBase>.Update(categoryBase);
            }

        }

        public ProductCategory GetProductCategoryDetail(Guid categoryGuid)
        {
            return ActiveRecordMediator<ProductCategory>.FindByPrimaryKey(categoryGuid);
        }

        public IList<ProductCategoryBase> GetProductCategoryRootlist()
        {
            return
                ActiveRecordMediator<ProductCategoryBase>.FindAll(
                    Expression.And(Expression.Eq("Parent", Guid.Empty), Expression.Eq("IsDeleteObject", false)));
        }

        public IList<ProductCategoryBase> GetProductCategoryList(ICriterion criterion)
        {
            ProductCategoryBase[] arrayValue = ActiveRecordMediator<ProductCategoryBase>.FindAll(criterion);
            return arrayValue == null ? new List<ProductCategoryBase>() : arrayValue as IList<ProductCategoryBase>;
        }

        public void CreateProduct(Product product)
        {
            product.IsNewObject = true;
            ActiveRecordMediator<Product>.Create(product);
        }

        public void UpdateProduct(Product product)
        {
            product.IsModifyObject = !product.IsNewObject;
            ActiveRecordMediator<Product>.Update(product);
        }

        public void DeleteProduct(Guid productGuid)
        {
            Product delProduct = ActiveRecordMediator<Product>.FindByPrimaryKey(productGuid);
            if (delProduct != null)
            {
                string imgId = delProduct.ImagePath;
                delProduct.ImagePath = "";
                if (!string.IsNullOrEmpty(imgId)) dataStorage.DeleteData(new Guid(imgId));
                delProduct.IsDeleteObject = true;
                ActiveRecordMediator<Product>.Update(delProduct);
            }
        }

        public byte[] LoadProductImage(string storageCode)
        {
            return dataStorage.GetData(new Guid(storageCode));
        }

        public string SaveProductImage(byte[] imageData)
        {
            Guid storageKey = Guid.NewGuid();
            dataStorage.SaveData(storageKey, imageData);
            return storageKey.ToString("N");
        }

        public void DeleteProductImage(string storageCode)
        {
            dataStorage.DeleteData(new Guid(storageCode));
        }

        //public CompanyProductLog AddProductToCompany(Guid productGuid, Guid companyGuid)
        //{
        //    CompanyProductLog cp = new CompanyProductLog();
        //    cp.IsNewObject = true;
        //    cp.Company = ActiveRecordMediator<Company>.FindByPrimaryKey(companyGuid);
        //    cp.Product = ActiveRecordMediator<Product>.FindByPrimaryKey(productGuid);
        //    ActiveRecordMediator<CompanyProductLog>.Create(cp);
        //    return cp;
        //}

        //public IList<CompanyProductLog> SearchCompanyProduct(string keyword, Guid companyGuid)
        //{
        //    throw new NotImplementedException();
        //}

        public void CreateProductMark(CompanyProductMark productMark)
        {
            productMark.IsNewObject = true;
            ActiveRecordMediator<CompanyProductMark>.Create(productMark);
        }

        public void UpdateProductMark(CompanyProductMark productMark)
        {
            productMark.IsNewObject = !productMark.IsModifyObject;
            ActiveRecordMediator<CompanyProductMark>.Save(productMark);
        }

        public void DeleteProductMark(Guid prodcutMarkGuid)
        {
            CompanyProductMark productMrk = ActiveRecordMediator<CompanyProductMark>.FindByPrimaryKey(prodcutMarkGuid);
            productMrk.IsDeleteObject = true;
            ActiveRecordMediator<CompanyProductMark>.Save(productMrk);
        }

        public void CreateProductTradeLog(ProductTradeLog tradeLog)
        {
            tradeLog.IsNewObject = true;
            ActiveRecordMediator<ProductTradeLog>.Create(tradeLog);
        }

        public void UpdateProductTradeLog(ProductTradeLog tradeLog)
        {
            tradeLog.IsModifyObject = !tradeLog.IsNewObject;
            ActiveRecordMediator<ProductTradeLog>.Save(tradeLog);
        }

        public IList<ProductTradeLog> GetProductTradeLog(ICriterion criterion, int pageIndex, int pageSize, params Order[] orderBy)
        {
            throw new System.NotImplementedException();
            
        }

        public int CalcProductTradeLogCount(ICriterion criterion)
        {
            throw new System.NotImplementedException();
        }
    }
}